#include "map.h"


Map::Map(void)
{
  this->isLoaded = false;
}


Map::~Map(void)
{
}


void Map::Load(LPWSTR filePath) {

  /* Manager release all objects */
  
  if(this->isLoaded == true) {
    ObjectsManager::getInstance()->RemoveAll();
    RenderableManager::getInstance()->RemoveAll();
    ControllableManager::getInstance()->RemoveAll();
    CollisionableManager::getInstance()->RemoveAll();
    EventableManager::getInstance()->RemoveAll();
    TexturesManager::getInstance()->RemoveAll();
  }

  /* Prepare file */

  HANDLE handleFile = CreateFileW(
      filePath, 
      FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if(handleFile == NULL) { // check handle created or not
    CloseHandle(handleFile);
    Log::Write(L"Open map file fail: ", filePath); 
    return;
  }
  // Get file size in byte.
  LARGE_INTEGER fileSize;
  GetFileSizeEx(handleFile, &fileSize);
  // Read file to CString object
  LPWSTR tempStr;
  ReadFile(handleFile, tempStr, fileSize.LowPart, NULL, NULL);
  CString data;
  data.SetString(tempStr);
  // split string to many path
  CString properties;
  CString textures;
  CString objects;
  int curPos = 0; // curent position of tokenize
  data.Tokenize(L"[property]", curPos); // drop property header
  properties = data.Tokenize(L"[texture]", curPos);
  textures = data.Tokenize(L"[object]", curPos);
  objects = data.Tokenize(L"[end]", curPos);

  /* Load property */

  int lines = this->CountLine(properties);
  CString* propertyArray = new CString[lines];
  this->SplitString(propertyArray, properties, L"\r\n", lines);
  //Load map back color 
  this->backColor = this->ColorFromString(propertyArray[0]);
  // Next map 
  this->nextMapName = propertyArray[1];
  this->nextMapPath = propertyArray[2];

  /* Load texture */

  lines = this->CountLine(textures);
  CString* texutureArray = new CString[lines];
  this->SplitString(texutureArray, textures, L"\r\n", lines);
  TexturesManager* textureManager = TexturesManager::getInstance();
  for(int i = 0; i < lines; i++) {
    CString* textureParams = new CString[3]; // path, id, transcolor
    this->SplitString(textureParams, texutureArray[i], L">", 3);
    D3DXCOLOR transcolor = this->ColorFromString(textureParams[2]);
    int textureId = _wtoi(textureParams[0]);
    LPWSTR texturePath = (LPWSTR)textureParams[1].GetString();
    textureManager->Add(textureId, texturePath, transcolor); 
  }

  /* Load objects */

  lines = this->CountLine(objects);
  CString* objectArray = new CString[lines];
  this->SplitString(objectArray, objects, L"\r\n", lines);
  for(int i = 0; i < lines; i++) {
    CString tmp = objectArray[i];
    int numAttribute = this->CountLine(tmp, L" ");
    CString* attributes = new CString[numAttribute];
    this->SplitString(attributes, tmp, L" ", numAttribute);
    int classId = _wtoi(attributes[0]);
    
    /* Find class name and create object */

    switch (classId) {
    case CLASS_ID_PLAYER:
      {
        Player player;
        player.FromArray(attributes);
        break;
      }

    }
    
  }
  // Map is loaded
  this->isLoaded = true;
}


void Map::Save(LPWSTR filePath) {

}



int Map::CountLine(CString string) {
  int result = 0;
  int curPos = 0;
  do {
    CString temp = string.Tokenize(L"\r\n", curPos);
    if(temp != "") {
      result++;
    } else {
      break;
    }
  } while (true);
  return result;
}


int Map::CountLine(CString string, LPCWSTR spliter) {
  int result = 0;
  int curPos = 0;
  do {
    CString temp = string.Tokenize(spliter, curPos);
    if(temp != "") {
      result++;
    } else {
      break;
    }
  } while (true);
  return result;
}



void Map::SplitString(CString* &str, CString input, LPWSTR spliter, int length){
  int curPos = 0;
  for(int i = 0; i < length; i++) {
    str[i] = input.Tokenize(spliter, curPos);
  }
}


D3DXCOLOR Map::ColorFromString(CString colorPart) {
  CString* colorParams = new CString[4];// D3DXCOLOR have four param
  this->SplitString(colorParams, colorPart, L" ", 4);
  int red = _wtoi(colorParams[0]);
  int green = _wtoi(colorParams[1]);
  int blue = _wtoi(colorParams[2]);
  int alpha = _wtoi(colorParams[3]);
  D3DXCOLOR color = D3DXCOLOR(red, green, blue, alpha);
  return color;
}
